#pragma once

#include <metalc/cls/_cls.h>
// 索引式
// tc malloc 0-1024 8字节分割 1024-32768 128字节分割

#define TC_SMALL_SIZE		(1024UL)
// #define TC_SMALL_STEP		(8UL)
#define TC_MAX_SIZE		(32768UL)
#define TC_MAX_STEP		(128UL)

#define TC_MIN_ALIGNED		
#define TC_SMALL_SIZE_CLASS(x, minbit)	((((unsigned long)x + BIT(minbit) - 1) >> (minbit))) /* 注意这里+1是确保最低大小大于sizeof(dword_t)*/
#define TC_LARGE_SIZE_CLASS(x) 		(((size_t)x + 127 + (120 << 7)) >> 7)
#define TC_CLS2SZ_SMALL(cls, minbit)	((cls) << (minbit))	
#define TC_CLS2SZ_LARGE(cls, minbit)	(TC_SMALL_SIZE + (((cls) - TC_SMALL_CLASSES(minbit)) << 7))

#define __sz2cls_tc(sz, minbit)		((sz) <= TC_SMALL_SIZE ? TC_SMALL_SIZE_CLASS(sz, minbit) : TC_LARGE_SIZE_CLASS(sz))
#define __cls2sz_tc(cls, minbit)	((cls) <= TC_SMALL_CLASSES(minbit) ? TC_CLS2SZ_SMALL(cls, minbit) : TC_CLS2SZ_LARGE(cls, minbit))
// #define TC_SMALL_SIZE_CLASS(x) (((size_t)x + (TC_SMALL_STEP - 1)) >> log2_align(TC_SMALL_STEP))
// #define TC_LARGE_SIZE_CLASS(x) (((size_t)x + (TC_MAX_STEP - 1) + ((TC_MAX_STEP - TC_SMALL_STEP) << log2_align(TC_MAX_STEP))) >> log2_align(TC_MAX_STEP))
#define TC_SMALL_CLASSES(minbit)	(TC_SMALL_SIZE/BIT(minbit))

#define TC_TOTAL_CLASSES(minbit)	(TC_SMALL_CLASSES(minbit) + (TC_MAX_SIZE - TC_SMALL_SIZE)/TC_MAX_STEP)

// DECL_SZLCS(tc)

#define CLS_NR_tc(bits_min, bits_max)		(TC_SMALL_CLASSES(bits_min))
#define CLS_ASSERT_tc(bits_min, bits_max)	((BIT(bits_max) == TC_MAX_SIZE) && (BIT(bits_min) == TC_SMALL_STEP))

/* 主要是用LIKELY标记 */
SAI PURE szcls_t __sz2cls_tc_(size_t size, const size_t minbit){
	szcls_t cls;
	/* 防止size == 8 */
	if (size < sizeof(dword_t)) size = sizeof(dword_t);
	if (LIKELY(size <= TC_SMALL_SIZE)) {
		cls = TC_SMALL_SIZE_CLASS(size, minbit);
	} else {
		cls = TC_LARGE_SIZE_CLASS(size);
	}
	return cls;
}

SAI PURE size_t __cls2sz_tc_(szcls_t cls, const size_t minbit){
	size_t sz;
	if(LIKELY(cls <= TC_SMALL_CLASSES(minbit))) sz = TC_CLS2SZ_SMALL(cls, minbit);
	else sz = TC_CLS2SZ_LARGE(cls, minbit);
	return sz;
}


#define DEF_CLS_TC(name, MINSZBIT, MAXSZBIT)					\
DECL_SZLCS(name)								\
SASSERT(MAXSZBIT > MINSZBIT);							\
SASSERT(BIT(MAXSZBIT) <= TC_MAX_SIZE);						\
static const szcls_t _clsnr_##name = TC_TOTAL_CLASSES(MINSZBIT);				\
static const size_t _maxsz_##name = __cls2sz_tc(TC_TOTAL_CLASSES(MINSZBIT) - 1, MINSZBIT);\
SAI PURE szcls_t _sz2cls_##name (size_t size){ return __sz2cls_tc_(size, MINSZBIT); };	\
SAI PURE size_t _cls2sz_##name (szcls_t cls){ return __cls2sz_tc_(cls, MINSZBIT); };
